"""
IP管理模块界面组件
"""

import logging
from typing import Dict, Any, List, Optional
from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QSplitter,
    QGroupBox, QLabel, QComboBox, QLineEdit, QPushButton, QTableWidget,
    QTableWidgetItem, QHeaderView, QTextEdit, QTabWidget, QProgressBar,
    QMessageBox, QMenu, QAction
)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
from PyQt5.QtGui import QFont, QDesktopServices

from src.app.modules.ip.service import IpService
from src.app.modules.ip.cache import IpCache
from src.app.modules.ip.utils import IpUtils
from src.app.modules.ip.ui.ip_dialog import IpDialog

logger = logging.getLogger(__name__)

class IpWidget(QWidget):
    """IP管理界面组件"""
    
    # 信号定义
    status_message = pyqtSignal(str)
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.service = IpService()
        self.cache = IpCache()
        self.utils = IpUtils()
        self.current_data = []
        self.current_filters = {}
        
        # 初始化UI
        self.init_ui()
        
        # 设置定时刷新
        self.refresh_timer = QTimer()
        self.refresh_timer.timeout.connect(self.refresh_statistics)
        self.refresh_timer.start(30000)
        
        # 延迟加载数据
        QTimer.singleShot(100, self.load_data)
    
    def init_ui(self):
        """初始化用户界面"""
        layout = QVBoxLayout(self)
        
        # 创建分割器
        splitter = QSplitter(Qt.Vertical)
        layout.addWidget(splitter)
        
        # 上部分：统计信息和筛选
        top_widget = self.create_top_widget()
        splitter.addWidget(top_widget)
        
        # 下部分：列表和详情
        bottom_widget = self.create_bottom_widget()
        splitter.addWidget(bottom_widget)
        
        # 设置分割器比例
        splitter.setSizes([200, 500])
    
    def create_top_widget(self) -> QWidget:
        """创建上部分组件"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 统计信息组
        self.stats_group = self.create_statistics_group()
        layout.addWidget(self.stats_group)
        
        # 筛选条件组
        self.filter_group = self.create_filter_group()
        layout.addWidget(self.filter_group)
        
        return widget
    
    def create_statistics_group(self) -> QGroupBox:
        """创建统计信息组"""
        stats_group = QGroupBox("IP地址统计")
        stats_layout = QGridLayout(stats_group)
        
        # 总数统计
        stats_layout.addWidget(QLabel("IP总数:"), 0, 0)
        self.total_count_label = QLabel("0")
        self.total_count_label.setStyleSheet(
            "font-size: 24px; font-weight: bold; color: #2196F3;"
        )
        stats_layout.addWidget(self.total_count_label, 0, 1)
        
        # 使用中统计
        stats_layout.addWidget(QLabel("使用中:"), 0, 2)
        self.in_use_count_label = QLabel("0")
        self.in_use_count_label.setStyleSheet(
            "font-size: 24px; font-weight: bold; color: #4CAF50;"
        )
        stats_layout.addWidget(self.in_use_count_label, 0, 3)
        
        # 可用统计
        stats_layout.addWidget(QLabel("可用:"), 1, 0)
        self.available_count_label = QLabel("0")
        self.available_count_label.setStyleSheet(
            "font-size: 24px; font-weight: bold; color: #FF9800;"
        )
        stats_layout.addWidget(self.available_count_label, 1, 1)
        
        # VLAN分布
        stats_layout.addWidget(QLabel("VLAN数量:"), 1, 2)
        self.vlan_count_label = QLabel("0")
        self.vlan_count_label.setStyleSheet(
            "font-size: 24px; font-weight: bold; color: #9C27B0;"
        )
        stats_layout.addWidget(self.vlan_count_label, 1, 3)
        
        return stats_group
    
    def create_filter_group(self) -> QGroupBox:
        """创建筛选条件组"""
        filter_group = QGroupBox("筛选条件")
        filter_layout = QGridLayout(filter_group)
        
        # VLAN筛选
        filter_layout.addWidget(QLabel("VLAN:"), 0, 0)
        self.vlan_combo = QComboBox()
        self.vlan_combo.addItem("全部VLAN", "")
        filter_layout.addWidget(self.vlan_combo, 0, 1)
        
        # 状态筛选
        filter_layout.addWidget(QLabel("状态:"), 0, 2)
        self.status_combo = QComboBox()
        self.status_combo.addItem("全部状态", "")
        for option in self.utils.get_status_options():
            self.status_combo.addItem(option['label'], option['value'])
        filter_layout.addWidget(self.status_combo, 0, 3)
        
        # 用途筛选
        filter_layout.addWidget(QLabel("用途:"), 1, 0)
        self.purpose_combo = QComboBox()
        self.purpose_combo.addItem("全部用途", "")
        for option in self.utils.get_purpose_options():
            self.purpose_combo.addItem(option['label'], option['value'])
        filter_layout.addWidget(self.purpose_combo, 1, 1)
        
        # 搜索框
        filter_layout.addWidget(QLabel("搜索:"), 1, 2)
        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText("输入IP地址或主机名...")
        filter_layout.addWidget(self.search_edit, 1, 3)
        
        # 操作按钮
        button_layout = QHBoxLayout()
        
        self.search_button = QPushButton("🔍 搜索")
        self.search_button.clicked.connect(self.on_search_clicked)
        button_layout.addWidget(self.search_button)
        
        self.reset_button = QPushButton("🔄 重置")
        self.reset_button.clicked.connect(self.on_reset_clicked)
        button_layout.addWidget(self.reset_button)
        
        self.export_button = QPushButton("📤 导出")
        self.export_button.clicked.connect(self.on_export_clicked)
        button_layout.addWidget(self.export_button)
        
        filter_layout.addLayout(button_layout, 2, 0, 1, 4)
        
        return filter_group
    
    def create_bottom_widget(self) -> QWidget:
        """创建下部分组件"""
        widget = QWidget()
        layout = QHBoxLayout(widget)
        
        # 创建分割器
        splitter = QSplitter(Qt.Horizontal)
        layout.addWidget(splitter)
        
        # 左侧：数据列表
        left_widget = self.create_list_widget()
        splitter.addWidget(left_widget)
        
        # 右侧：详情面板
        right_widget = self.create_detail_widget()
        splitter.addWidget(right_widget)
        
        # 设置分割器比例
        splitter.setSizes([400, 200])
        
        return widget
    
    def create_list_widget(self) -> QWidget:
        """创建数据列表组件"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 标题和操作按钮
        title_layout = QHBoxLayout()
        
        title_label = QLabel("IP地址列表")
        title_font = QFont()
        title_font.setBold(True)
        title_font.setPointSize(12)
        title_label.setFont(title_font)
        title_layout.addWidget(title_label)
        
        title_layout.addStretch()
        
        self.add_button = QPushButton("➕ 新增IP")
        self.add_button.clicked.connect(self.on_add_clicked)
        title_layout.addWidget(self.add_button)
        
        self.edit_button = QPushButton("✏️ 编辑")
        self.edit_button.clicked.connect(self.on_edit_clicked)
        self.edit_button.setEnabled(False)
        title_layout.addWidget(self.edit_button)
        
        self.delete_button = QPushButton("🗑️ 删除")
        self.delete_button.clicked.connect(self.on_delete_clicked)
        self.delete_button.setEnabled(False)
        title_layout.addWidget(self.delete_button)
        
        layout.addLayout(title_layout)
        
        # 数据表格
        self.data_table = QTableWidget()
        self.data_table.setColumnCount(6)
        self.data_table.setHorizontalHeaderLabels([
            "IP地址", "VLAN", "状态", "用途", "主机名", "绑定实体"
        ])
        
        # 设置表格属性
        header = self.data_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.Stretch)
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(4, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(5, QHeaderView.ResizeToContents)
        
        self.data_table.setAlternatingRowColors(True)
        self.data_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.data_table.setSelectionMode(QTableWidget.SingleSelection)
        self.data_table.itemSelectionChanged.connect(self.on_selection_changed)
        self.data_table.itemDoubleClicked.connect(self.on_item_double_clicked)
        self.data_table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.data_table.customContextMenuRequested.connect(self.show_context_menu)
        
        layout.addWidget(self.data_table)
        
        return widget
    
    def create_detail_widget(self) -> QWidget:
        """创建详情面板组件"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 标题
        title_label = QLabel("详细信息")
        title_font = QFont()
        title_font.setBold(True)
        title_font.setPointSize(12)
        title_label.setFont(title_font)
        layout.addWidget(title_label)
        
        # 标签页
        self.detail_tabs = QTabWidget()
        
        # 基本信息标签页
        basic_widget = QWidget()
        basic_layout = QVBoxLayout(basic_widget)
        
        self.basic_info_text = QTextEdit()
        self.basic_info_text.setReadOnly(True)
        basic_layout.addWidget(self.basic_info_text)
        
        self.detail_tabs.addTab(basic_widget, "基本信息")
        
        # 网络信息标签页
        network_widget = QWidget()
        network_layout = QVBoxLayout(network_widget)
        
        self.network_info_text = QTextEdit()
        self.network_info_text.setReadOnly(True)
        network_layout.addWidget(self.network_info_text)
        
        self.detail_tabs.addTab(network_widget, "网络信息")
        
        # 绑定实体标签页
        entity_widget = QWidget()
        entity_layout = QVBoxLayout(entity_widget)
        
        self.entity_info_text = QTextEdit()
        self.entity_info_text.setReadOnly(True)
        entity_layout.addWidget(self.entity_info_text)
        
        self.detail_tabs.addTab(entity_widget, "绑定实体")
        
        layout.addWidget(self.detail_tabs)
        
        return widget
    
    def load_data(self):
        """加载数据"""
        try:
            self.status_message.emit("正在加载IP地址数据...")
            
            # 加载统计数据
            self.refresh_statistics()
            
            # 加载筛选选项
            self.load_filter_options()
            
            # 加载IP列表
            self.refresh_ip_list()
            
            self.status_message.emit("IP地址数据加载完成")
            
        except Exception as e:
            logger.error(f"加载IP地址数据失败: {str(e)}")
            self.status_message.emit(f"加载失败: {str(e)}")
    
    def refresh_statistics(self):
        """刷新统计信息"""
        try:
            # 先从缓存获取
            cached_stats = self.cache.get_statistics()
            if cached_stats:
                self.update_statistics_display(cached_stats)
                return
            
            # 从数据库获取
            statistics = self.service.get_ip_statistics()
            
            # 更新显示
            self.update_statistics_display(statistics)
            
            # 缓存数据
            self.cache.set_statistics(statistics)
            
        except Exception as e:
            logger.error(f"刷新统计信息失败: {str(e)}")
    
    def update_statistics_display(self, statistics: Dict[str, Any]):
        """更新统计信息显示"""
        self.total_count_label.setText(str(statistics.get('total_count', 0)))
        self.in_use_count_label.setText(str(statistics.get('status_distribution', {}).get('使用中', 0)))
        self.available_count_label.setText(str(statistics.get('status_distribution', {}).get('可用', 0)))
        self.vlan_count_label.setText(str(len(statistics.get('vlan_distribution', {}))))
    
    def load_filter_options(self):
        """加载筛选选项"""
        try:
            # 获取所有VLAN选项
            ip_list = self.service.get_all_ips()
            vlans = set()
            for ip_data in ip_list:
                if ip_data.get('vlan'):
                    vlans.add(ip_data['vlan'])
            
            # 更新VLAN下拉框
            current_text = self.vlan_combo.currentText()
            self.vlan_combo.clear()
            self.vlan_combo.addItem("全部VLAN", "")
            
            for vlan in sorted(vlans):
                self.vlan_combo.addItem(vlan, vlan)
            
            # 恢复之前的选择
            for i in range(self.vlan_combo.count()):
                if self.vlan_combo.itemText(i) == current_text:
                    self.vlan_combo.setCurrentIndex(i)
                    break
                    
        except Exception as e:
            logger.error(f"加载筛选选项失败: {str(e)}")
    
    def refresh_ip_list(self):
        """刷新IP列表"""
        try:
            # 构建筛选条件
            filters = {}
            
            vlan = self.vlan_combo.currentData()
            if vlan:
                filters['vlan'] = vlan
            
            status = self.status_combo.currentData()
            if status:
                filters['status'] = status
            
            purpose = self.purpose_combo.currentData()
            if purpose:
                filters['purpose'] = purpose
            
            search_text = self.search_edit.text().strip()
            if search_text:
                # 判断搜索内容是IP还是主机名
                if self.utils.is_valid_ip(search_text):
                    filters['ip'] = search_text
                else:
                    filters['hostname'] = search_text
            
            # 生成筛选条件哈希
            filters_hash = self.cache.generate_filters_hash(filters)
            
            # 先从缓存获取
            cached_list = self.cache.get_ip_list(filters_hash)
            if cached_list:
                self.current_data = cached_list
                self.update_table_display()
                return
            
            # 从数据库获取
            ip_list = self.service.get_all_ips(filters)
            
            # 更新数据
            self.current_data = ip_list
            self.update_table_display()
            
            # 缓存数据
            self.cache.set_ip_list(filters_hash, ip_list)
            
        except Exception as e:
            logger.error(f"刷新IP列表失败: {str(e)}")
            self.status_message.emit(f"刷新列表失败: {str(e)}")
    
    def update_table_display(self):
        """更新表格显示"""
        try:
            self.data_table.setRowCount(len(self.current_data))
            
            for row, ip_data in enumerate(self.current_data):
                # IP地址
                self.data_table.setItem(row, 0, QTableWidgetItem(ip_data['ip']))
                
                # VLAN
                self.data_table.setItem(row, 1, QTableWidgetItem(ip_data['vlan']))
                
                # 状态
                status_text = self.utils.format_ip_status(ip_data['status'])
                self.data_table.setItem(row, 2, QTableWidgetItem(status_text))
                
                # 用途
                purpose_text = self.utils.format_purpose(ip_data['purpose'])
                self.data_table.setItem(row, 3, QTableWidgetItem(purpose_text))
                
                # 主机名
                hostname = ip_data.get('hostname', '')
                self.data_table.setItem(row, 4, QTableWidgetItem(hostname))
                
                # 绑定实体
                entity_type = self.utils.get_binding_entity_type(ip_data)
                self.data_table.setItem(row, 5, QTableWidgetItem(entity_type))
            
        except Exception as e:
            logger.error(f"更新表格显示失败: {str(e)}")
    
    def update_detail_display(self, ip_data: Dict[str, Any]):
        """更新详情显示"""
        try:
            # 更新基本信息
            basic_info = self.format_basic_info(ip_data)
            self.basic_info_text.setPlainText(basic_info)
            
            # 更新网络信息
            network_info = self.format_network_info(ip_data)
            self.network_info_text.setPlainText(network_info)
            
            # 更新绑定实体信息
            entity_info = self.service.get_binding_entities(ip_data['ip'])
            entity_text = self.format_entity_info(entity_info)
            self.entity_info_text.setPlainText(entity_text)
            
        except Exception as e:
            logger.error(f"更新详情显示失败: {str(e)}")
    
    def format_basic_info(self, ip_data: Dict[str, Any]) -> str:
        """格式化基本信息"""
        info = []
        info.append(f"IP地址: {ip_data['ip']}")
        info.append(f"子网掩码: {ip_data['subnet_mask']}")
        info.append(f"VLAN: {ip_data['vlan']}")
        info.append(f"状态: {self.utils.format_ip_status(ip_data['status'])}")
        info.append(f"用途: {self.utils.format_purpose(ip_data['purpose'])}")
        info.append(f"分配期限: {ip_data['allocation_duration']}")
        
        if ip_data.get('hostname'):
            info.append(f"主机名: {ip_data['hostname']}")
        
        if ip_data.get('os_name'):
            info.append(f"操作系统: {ip_data['os_name']}")
        
        if ip_data.get('description'):
            info.append(f"描述: {ip_data['description']}")
        
        info.append(f"创建时间: {ip_data.get('create_time', '')}")
        info.append(f"更新时间: {ip_data.get('update_time', '')}")
        
        return '\n'.join(info)
    
    def format_network_info(self, ip_data: Dict[str, Any]) -> str:
        """格式化网络信息"""
        network_info = self.utils.get_network_info(
            ip_data['ip'], 
            ip_data['subnet_mask']
        )
        
        if not network_info:
            return "网络信息获取失败"
        
        info = []
        info.append(f"网络地址: {network_info.get('network_address', '')}")
        info.append(f"广播地址: {network_info.get('broadcast_address', '')}")
        info.append(f"网络掩码: {network_info.get('netmask', '')}")
        info.append(f"前缀长度: {network_info.get('prefix_length', '')}")
        info.append(f"可用地址数: {network_info.get('num_addresses', '')}")
        info.append(f"是否私有地址: {'是' if network_info.get('is_private') else '否'}")
        
        return '\n'.join(info)
    
    def format_entity_info(self, entity_info: Dict[str, Any]) -> str:
        """格式化绑定实体信息"""
        if not entity_info:
            return "未绑定任何实体"
        
        info = []
        for entity_type, entity_data in entity_info.items():
            info.append(f"实体类型: {entity_data['type']}")
            info.append(f"名称: {entity_data['name']}")
            
            if 'code' in entity_data:
                info.append(f"编码: {entity_data['code']}")
            
            if 'version' in entity_data:
                info.append(f"版本: {entity_data['version']}")
            
            if 'asset_type' in entity_data:
                info.append(f"设备类型: {entity_data['asset_type']}")
            
            if 'system_type' in entity_data:
                info.append(f"系统类型: {entity_data['system_type']}")
            
            if 'mw_type' in entity_data:
                info.append(f"中间件类型: {entity_data['mw_type']}")
            
            info.append("---")
        
        return '\n'.join(info)
    
    def on_selection_changed(self):
        """选择变化事件"""
        try:
            selected_rows = self.data_table.selectedItems()
            if selected_rows:
                row = selected_rows[0].row()
                ip_data = self.current_data[row]
                
                # 更新详情显示
                self.update_detail_display(ip_data)
                
                # 启用操作按钮
                self.edit_button.setEnabled(True)
                self.delete_button.setEnabled(True)
            else:
                # 清空详情显示
                self.basic_info_text.clear()
                self.network_info_text.clear()
                self.entity_info_text.clear()
                
                # 禁用操作按钮
                self.edit_button.setEnabled(False)
                self.delete_button.setEnabled(False)
                
        except Exception as e:
            logger.error(f"选择变化处理失败: {str(e)}")
    
    def on_item_double_clicked(self, item):
        """双击项目事件"""
        try:
            row = item.row()
            ip_data = self.current_data[row]
            self.edit_ip(ip_data)
        except Exception as e:
            logger.error(f"双击处理失败: {str(e)}")
    
    def show_context_menu(self, position):
        """显示右键菜单"""
        try:
            item = self.data_table.itemAt(position)
            if not item:
                return
            
            menu = QMenu(self)
            
            edit_action = QAction("✏️ 编辑", self)
            edit_action.triggered.connect(lambda: self.on_edit_clicked())
            menu.addAction(edit_action)
            
            delete_action = QAction("🗑️ 删除", self)
            delete_action.triggered.connect(lambda: self.on_delete_clicked())
            menu.addAction(delete_action)
            
            menu.addSeparator()
            
            refresh_action = QAction("🔄 刷新", self)
            refresh_action.triggered.connect(lambda: self.refresh_ip_list())
            menu.addAction(refresh_action)
            
            menu.exec_(self.data_table.mapToGlobal(position))
            
        except Exception as e:
            logger.error(f"显示右键菜单失败: {str(e)}")
    
    def on_search_clicked(self):
        """搜索按钮点击事件"""
        self.refresh_ip_list()
    
    def on_reset_clicked(self):
        """重置按钮点击事件"""
        self.vlan_combo.setCurrentIndex(0)
        self.status_combo.setCurrentIndex(0)
        self.purpose_combo.setCurrentIndex(0)
        self.search_edit.clear()
        self.refresh_ip_list()
    
    def on_export_clicked(self):
        """导出按钮点击事件"""
        try:
            if not self.current_data:
                QMessageBox.warning(self, "警告", "没有数据可导出")
                return
            
            # 这里可以添加导出逻辑
            self.status_message.emit("导出功能开发中...")
            
        except Exception as e:
            logger.error(f"导出失败: {str(e)}")
            self.status_message.emit(f"导出失败: {str(e)}")
    
    def on_add_clicked(self):
        """新增按钮点击事件"""
        try:
            dialog = IpDialog(self)
            if dialog.exec_() == IpDialog.Accepted:
                self.refresh_ip_list()
                self.refresh_statistics()
                self.status_message.emit("IP地址添加成功")
        except Exception as e:
            logger.error(f"添加IP地址失败: {str(e)}")
            self.status_message.emit(f"添加失败: {str(e)}")
    
    def on_edit_clicked(self):
        """编辑按钮点击事件"""
        try:
            selected_rows = self.data_table.selectedItems()
            if not selected_rows:
                return
            
            row = selected_rows[0].row()
            ip_data = self.current_data[row]
            self.edit_ip(ip_data)
            
        except Exception as e:
            logger.error(f"编辑IP地址失败: {str(e)}")
    
    def edit_ip(self, ip_data: Dict[str, Any]):
        """编辑IP地址"""
        try:
            dialog = IpDialog(self, ip_data)
            if dialog.exec_() == IpDialog.Accepted:
                self.refresh_ip_list()
                self.refresh_statistics()
                self.status_message.emit("IP地址更新成功")
        except Exception as e:
            logger.error(f"编辑IP地址失败: {str(e)}")
            self.status_message.emit(f"编辑失败: {str(e)}")
    
    def on_delete_clicked(self):
        """删除按钮点击事件"""
        try:
            selected_rows = self.data_table.selectedItems()
            if not selected_rows:
                return
            
            row = selected_rows[0].row()
            ip_data = self.current_data[row]
            ip_address = ip_data['ip']
            
            # 确认删除
            reply = QMessageBox.question(
                self, "确认删除",
                f"确定要删除IP地址 {ip_address} 吗？\n\n此操作不可恢复！",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No
            )
            
            if reply == QMessageBox.Yes:
                result = self.service.delete_ip(ip_address)
                if result['success']:
                    self.refresh_ip_list()
                    self.refresh_statistics()
                    self.status_message.emit("IP地址删除成功")
                else:
                    QMessageBox.warning(self, "删除失败", result['message'])
                    self.status_message.emit(f"删除失败: {result['message']}")
                    
        except Exception as e:
            logger.error(f"删除IP地址失败: {str(e)}")
            self.status_message.emit(f"删除失败: {str(e)}")